package com.kvn.dubbo.filter;

import lombok.Data;
import lombok.experimental.Accessors;

import java.util.Arrays;
import java.util.List;

/**
 * Created by wangzhiyuan on 2019/1/31
 */
public class FilterTest {

    public static void main(String[] args) {
        Invoker invoker = buildInvokerChain(new BizInvoker());

        // 执行
        Invocation invocation = new Invocation() {}.setContext("hello");
        Object result = invoker.invoke(invocation);
        System.out.println("result = [" + result + "]");
    }

    public static Invoker buildInvokerChain(Invoker invoker){
        List<Filter> filters = Arrays.asList(new Filter1(), new Filter2());

        Invoker last = invoker;
        for (int i = filters.size() - 1; i >= 0; i--) {
            final Filter filter = filters.get(i);
            Invoker next = last;
            last = new Invoker() {
                @Override
                public Object invoke(Invocation invocation) {
                    return filter.invoke(next, invocation);
                }
            };
        }
        return last;
    }

}

////////////////////////////////////////////
interface Invoker {
    Object invoke(Invocation invocation);
}

@Data
@Accessors(chain = true)
abstract class Invocation {
    private String context;
}

interface Filter {
    Object invoke(Invoker invoker, Invocation invocation);
}
/////////////////////////////////////////

class BizInvoker implements Invoker {

    @Override
    public Object invoke(Invocation invocation) {
        System.out.println("BizInvoker 业务逻辑 --> invocation = [" + invocation + "]");
        return "成功";
    }
}

class Filter1 implements Filter {

    @Override
    public Object invoke(Invoker invoker, Invocation invocation) {
        System.out.println("Filter1111 --> invocation = [" + invocation + "]");
        invocation.setContext(invocation.getContext() + ":filter1添加");
        return invoker.invoke(invocation);
    }
}

class Filter2 implements Filter {

    @Override
    public Object invoke(Invoker invoker, Invocation invocation) {
        System.out.println("Filter2222 --> invocation = [" + invocation + "]");
        invocation.setContext(invocation.getContext() + ":filter2添加");
        return invoker.invoke(invocation);
    }
}
